home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / mac / DirectX SDK / DXSDK / samples / Multimedia / DirectShow_WinXP / VMR / VMRXcl / vcdplyer.cpp < prev    next >
C/C++ Source or Header  |  2001-10-10  |  13KB  |  505 lines

  1. //----------------------------------------------------------------------------
  2. //  File:   vcdplyer.cpp
  3. //
  4. //  Desc:   DirectShow sample code
  5. //          Implementation of CMpegMovie, a customized video player
  6. //
  7. //  Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
  8. //----------------------------------------------------------------------------
  9. #include "project.h"
  10. #include <mmreg.h>
  11. #include <commctrl.h>
  12.  
  13. #include <stdarg.h>
  14. #include <stdio.h>
  15.  
  16. #define MY_USER_ID 0x1234ACDE
  17.  
  18. //----------------------------------------------------------------------------
  19. // CMpegMovie
  20. //
  21. // Constructors and destructors
  22. //
  23. //----------------------------------------------------------------------------
  24. CMpegMovie::CMpegMovie(HWND hwndApplication)
  25.     : CUnknown(NAME("Allocator Presenter"), NULL),
  26.       m_hwndApp(hwndApplication),
  27.       m_MediaEvent(NULL),
  28.       m_Mode(MOVIE_NOTOPENED),
  29.       m_pBF(NULL),
  30.       m_Fg(NULL),
  31.       m_Gb(NULL),
  32.       m_Mc(NULL),
  33.       m_Ms(NULL),
  34.       m_Me(NULL),
  35.       m_Qp(NULL),
  36.       m_lpDefSAN(NULL),
  37.       m_iDuration(-1),
  38.       m_TimeFormat(TIME_FORMAT_MEDIA_TIME),
  39.       m_lpDefWC(NULL),
  40.       m_lpDefIP(NULL),
  41.       m_lpDefSA(NULL),
  42.       m_AlphaBlt(NULL)
  43.  
  44. {
  45.     AddRef();
  46. }
  47.  
  48. CMpegMovie::~CMpegMovie() {
  49.     ;
  50. }
  51.  
  52. //----------------------------------------------------------------------------
  53. // SetRenderingMode
  54. //
  55. // Set rendering mode of VMR (Windowless, Windowed, Renderless)
  56. //----------------------------------------------------------------------------
  57. HRESULT
  58. SetRenderingMode(
  59.     IBaseFilter* pBaseFilter,
  60.     VMRMode mode
  61.     )
  62. {
  63.     IVMRFilterConfig* pConfig;
  64.     HRESULT hr = pBaseFilter->QueryInterface(__uuidof(IVMRFilterConfig),
  65.                                              (LPVOID *)&pConfig);
  66.  
  67.     if( SUCCEEDED( hr )) {
  68.         pConfig->SetRenderingMode( mode );
  69.         pConfig->Release();
  70.     }
  71.     return hr;
  72. }
  73.  
  74. HRESULT CMpegMovie::AllocateAlphaBlt(void)
  75. {
  76.     HRESULT hRes=S_OK;
  77.  
  78.     m_AlphaBlt = new CAlphaBlt(m_pDDObject.GetBB(), &hRes);
  79.     return hRes;
  80. }
  81.  
  82. //----------------------------------------------------------------------------
  83. // AddVideoMixingRendererToFG()
  84. //
  85. // creates and adds VMR to the graph
  86. //----------------------------------------------------------------------------
  87. HRESULT
  88. CMpegMovie::AddVideoMixingRendererToFG()
  89. {
  90.     HRESULT hRes = S_OK;
  91.  
  92.     m_AlphaBlt = NULL;
  93.  
  94.     __try {
  95.         CHECK_HR(hRes = m_pDDObject.Initialize(m_hwndApp));
  96.  
  97.         CHECK_HR(hRes = CoCreateInstance(CLSID_VideoMixingRenderer,
  98.                                 NULL, CLSCTX_INPROC,IID_IBaseFilter,
  99.                                 (LPVOID *)&m_pBF));
  100.  
  101.         CHECK_HR(hRes = m_Fg->AddFilter(m_pBF, L"Video Mixing Renderer"));
  102.  
  103.         CHECK_HR(hRes = SetRenderingMode(m_pBF, VMRMode_Renderless));
  104.  
  105.         CHECK_HR(hRes = m_pBF->QueryInterface(__uuidof(IVMRSurfaceAllocatorNotify),
  106.                                 (LPVOID *)&m_lpDefSAN));
  107.  
  108.         hRes = AllocateAlphaBlt();
  109.         if (FAILED(hRes)) {
  110.             __leave;
  111.         }
  112.  
  113.  
  114.         CHECK_HR(hRes = CreateDefaultAllocatorPresenter(m_pDDObject.GetDDObj(),
  115.                                                         m_pDDObject.GetBB()));
  116.  
  117.         CHECK_HR(hRes = m_lpDefSAN->AdviseSurfaceAllocator(MY_USER_ID, this));
  118.     }
  119.     __finally {
  120.  
  121.         if (FAILED(hRes)) {
  122.             delete m_AlphaBlt;
  123.             m_AlphaBlt= NULL;
  124.             m_pDDObject.Terminate();
  125.         }
  126.     }
  127.  
  128.     return hRes;
  129. }
  130.  
  131.  
  132. //----------------------------------------------------------------------------
  133. // OpenMovie
  134. //
  135. // creates the graph, adds VMR, QIs relevant interfaces and renders the file
  136. //----------------------------------------------------------------------------
  137. HRESULT
  138. CMpegMovie::OpenMovie(
  139.     TCHAR *lpFileName
  140.     )
  141. {
  142.     IUnknown        *pUnk = NULL;
  143.     HRESULT         hres = S_OK;
  144.  
  145.     WCHAR           FileName[MAX_PATH];
  146.  
  147. #ifdef UNICODE
  148.     lstrcpy(FileName, lpFileName);
  149. #else
  150.     // wsprintfA((char*)FileName, "%hs", lpFileName);
  151.     MultiByteToWideChar(CP_ACP,0,(const char*) lpFileName, -1, FileName, MAX_PATH);
  152. #endif
  153.  
  154.     __try {
  155.         CHECK_HR(hres = CoCreateInstance(CLSID_FilterGraph,
  156.                                          NULL, CLSCTX_INPROC,
  157.                                          IID_IUnknown, (LPVOID *)&pUnk));
  158.         m_Mode = MOVIE_OPENED;
  159.         CHECK_HR(hres = pUnk->QueryInterface(IID_IFilterGraph, (LPVOID *)&m_Fg));
  160.         CHECK_HR(hres = AddVideoMixingRendererToFG());
  161.         CHECK_HR(hres = pUnk->QueryInterface(IID_IGraphBuilder, (LPVOID *)&m_Gb));
  162.         CHECK_HR(hres = m_Gb->RenderFile(FileName, NULL));
  163.         CHECK_HR(hres = pUnk->QueryInterface(IID_IMediaControl, (LPVOID *)&m_Mc));
  164.         CHECK_HR(hres = m_pBF->QueryInterface(IID_IQualProp, (LPVOID*)&m_Qp));
  165.  
  166.         //
  167.         // Not being able to get the IMediaEvent interface does
  168.         // necessarly mean that we can't play the graph.
  169.         //
  170.         HRESULT hr = pUnk->QueryInterface(IID_IMediaEvent, (LPVOID *)&m_Me);
  171.         GetMovieEventHandle();
  172.         pUnk->QueryInterface(IID_IMediaSeeking, (LPVOID *)&m_Ms);
  173.  
  174.     }
  175.     __finally {
  176.  
  177.         if (FAILED(hres)) {
  178.             RELEASE(m_Ms);
  179.             RELEASE(m_Me);
  180.             RELEASE(m_Mc);
  181.             RELEASE(m_Gb);
  182.             RELEASE(m_Fg);
  183.  
  184.             m_pDDObject.Terminate();
  185.         }
  186.  
  187.         RELEASE(pUnk);
  188.     }
  189.  
  190.     return hres;
  191. }
  192.  
  193.  
  194. //----------------------------------------------------------------------------
  195. //  CloseMovie
  196. //
  197. //  Releases client-provided allocator-presenter, exits sxclusive mode
  198. //----------------------------------------------------------------------------
  199. DWORD
  200. CMpegMovie::CloseMovie(
  201.     )
  202. {
  203.     m_Mode = MOVIE_NOTOPENED;
  204.  
  205.     RELEASE(m_Qp);
  206.     RELEASE(m_Mc);
  207.     RELEASE(m_Me);
  208.     RELEASE(m_Ms);
  209.     RELEASE(m_Gb);
  210.     RELEASE(m_Fg);
  211.  
  212.     if (m_lpDefSAN) {
  213.         m_lpDefSAN->AdviseSurfaceAllocator(0, NULL);
  214.         m_lpDefSAN->Release();
  215.     }
  216.  
  217.     RELEASE(m_pBF);
  218.     RELEASE(m_lpDefWC);
  219.     RELEASE(m_lpDefSA);
  220.     RELEASE(m_lpDefIP);
  221.  
  222.     delete m_AlphaBlt;
  223.     m_pDDObject.Terminate();
  224.  
  225.     return 0L;
  226. }
  227.  
  228.  
  229. //----------------------------------------------------------------------------
  230. // RepaintVideo
  231. //----------------------------------------------------------------------------
  232. BOOL
  233. CMpegMovie::RepaintVideo(
  234.     HWND hwnd,
  235.     HDC hdc
  236.     )
  237. {
  238.     BOOL bRet = FALSE;
  239.     if (m_lpDefWC) {
  240.         bRet = (m_lpDefWC->RepaintVideo(hwnd, hdc) == S_OK);
  241.     }
  242.  
  243.     return bRet;
  244. }
  245.  
  246.  
  247. //----------------------------------------------------------------------------
  248. // PutMoviePosition
  249. //----------------------------------------------------------------------------
  250. BOOL
  251. CMpegMovie::PutMoviePosition(
  252.     LONG x,
  253.     LONG y,
  254.     LONG cx,
  255.     LONG cy
  256.     )
  257. {
  258.     HRESULT hr;
  259.     BOOL bRet = FALSE;
  260.  
  261.     if (m_lpDefWC) {
  262.         RECT rc;
  263.         SetRect(&rc, x, y, x + cx, y + cy);
  264.         hr = m_lpDefWC->SetVideoPosition(NULL, &rc);
  265.         bRet = (hr == S_OK);
  266.     }
  267.  
  268.     return bRet;
  269. }
  270.  
  271.  
  272. //----------------------------------------------------------------------------
  273. //  PlayMovie
  274. //
  275. //  Just runs IMediaControl
  276. //
  277. //----------------------------------------------------------------------------
  278. BOOL
  279. CMpegMovie::PlayMovie(
  280.     )
  281. {
  282.     REFTIME rt;
  283.     REFTIME rtAbs;
  284.     REFTIME rtDur;
  285.  
  286.     rt = GetCurrentPosition();
  287.     rtDur = GetDuration();
  288.  
  289.     //
  290.     // If we are near the end of the movie seek to the start, otherwise
  291.     // stay where we are.
  292.     //
  293.     rtAbs = rt - rtDur;
  294.     if (rtAbs < (REFTIME)0) {
  295.         rtAbs = -rtAbs;
  296.     }
  297.  
  298.     if (rtAbs <= (REFTIME)1) {
  299.         SeekToPosition((REFTIME)0,FALSE);
  300.     }
  301.  
  302.     //
  303.     // Change mode after setting m_Mode but before starting the graph
  304.     //
  305.     m_Mode = MOVIE_PLAYING;
  306.     HRESULT hr = m_Mc->Run();
  307.     return TRUE;
  308. }
  309.  
  310.  
  311. //----------------------------------------------------------------------------
  312. // PauseMovie
  313. //
  314. //
  315. //----------------------------------------------------------------------------
  316. BOOL
  317. CMpegMovie::PauseMovie(
  318.     )
  319. {
  320.     m_Mode = MOVIE_PAUSED;
  321.     m_Mc->Pause();
  322.     return TRUE;
  323. }
  324.  
  325.  
  326. //----------------------------------------------------------------------------
  327. // GetStateMovie
  328. //
  329. // returns state of the media control (running, paused, or stopped)
  330. //----------------------------------------------------------------------------
  331.  
  332. OAFilterState
  333. CMpegMovie::GetStateMovie(
  334.     )
  335. {
  336.     OAFilterState State=0;
  337.     if (m_Mc)
  338.         m_Mc->GetState(INFINITE,&State);
  339.     return State;
  340. }
  341.  
  342.  
  343. //----------------------------------------------------------------------------
  344. // StopMovie
  345. //
  346. //----------------------------------------------------------------------------
  347. BOOL
  348. CMpegMovie::StopMovie(
  349.     )
  350. {
  351.     m_Mode = MOVIE_STOPPED;
  352.     m_Mc->Stop();
  353.     return TRUE;
  354. }
  355.  
  356.  
  357. //----------------------------------------------------------------------------
  358. // GetMediaEventHandle
  359. //
  360. // Returns the IMediaEvent event handle for the filter graph iff the
  361. // filter graph exists.
  362. //
  363. //----------------------------------------------------------------------------
  364. HANDLE
  365. CMpegMovie::GetMovieEventHandle(
  366.     )
  367. {
  368.     HRESULT     hr = S_OK;
  369.  
  370.     if (m_Me != NULL) {
  371.  
  372.         if ( m_MediaEvent == NULL) {
  373.             hr = m_Me->GetEventHandle((OAEVENT *)&m_MediaEvent);
  374.         }
  375.     }
  376.     else {
  377.         m_MediaEvent = NULL;
  378.     }
  379.     return m_MediaEvent;
  380. }
  381.  
  382.  
  383. //----------------------------------------------------------------------------
  384. // GetMovieEventCode
  385. //
  386. // Retrieves notification events from the graph through IMediaEvent interface
  387. //----------------------------------------------------------------------------
  388. long
  389. CMpegMovie::GetMovieEventCode()
  390. {
  391.     HRESULT hr;
  392.     long    lEventCode;
  393.     LONG_PTR    lParam1, lParam2;
  394.  
  395.     if (m_Me != NULL) {
  396.         hr = m_Me->GetEvent(&lEventCode, &lParam1, &lParam2, 0);
  397.         if (SUCCEEDED(hr)) {
  398.             return lEventCode;
  399.         }
  400.     }
  401.  
  402.     return 0L;
  403. }
  404.  
  405.  
  406. //----------------------------------------------------------------------------
  407. // GetDuration
  408. //
  409. // Returns the duration of the current movie
  410. // NOTE that time format may vary with different media types
  411. //
  412. //----------------------------------------------------------------------------
  413. REFTIME
  414. CMpegMovie::GetDuration()
  415. {
  416.     HRESULT hr;
  417.     LONGLONG Duration;
  418.  
  419.     // Should we seek using IMediaSelection
  420.  
  421.     if (m_Ms != NULL && m_TimeFormat != TIME_FORMAT_MEDIA_TIME) {
  422.         hr = m_Ms->GetDuration(&Duration);
  423.         if (SUCCEEDED(hr)) {
  424.             return double(Duration);
  425.         }
  426.     } else if (m_Ms != NULL) {
  427.         hr = m_Ms->GetDuration(&Duration);
  428.         if (SUCCEEDED(hr)) {
  429.             return double(Duration) / UNITS;
  430.         }
  431.     }
  432.     return 0;
  433. }
  434.  
  435.  
  436. //----------------------------------------------------------------------------
  437. // GetCurrentPosition
  438. //
  439. // Returns the duration of the current movie
  440. // NOTE that time format may vary with different media types
  441. //
  442. //----------------------------------------------------------------------------
  443. REFTIME
  444. CMpegMovie::GetCurrentPosition()
  445. {
  446.     REFTIME rt = (REFTIME)0;
  447.     HRESULT hr;
  448.     LONGLONG Position;
  449.  
  450.     // Should we return a media position
  451.  
  452.     if (m_Ms != NULL && m_TimeFormat != TIME_FORMAT_MEDIA_TIME) {
  453.         hr = m_Ms->GetPositions(&Position, NULL);
  454.         if (SUCCEEDED(hr)) {
  455.             return double(Position);
  456.         }
  457.     } else if (m_Ms != NULL) {
  458.         hr = m_Ms->GetPositions(&Position, NULL);
  459.         if (SUCCEEDED(hr)) {
  460.             return double(Position) / UNITS;
  461.         }
  462.     }
  463.     return rt;
  464. }
  465.  
  466.  
  467. //----------------------------------------------------------------------------
  468. // SeekToPosition
  469. //
  470. // NOTE that time format may vary with different media types
  471. //
  472. //----------------------------------------------------------------------------
  473. BOOL
  474. CMpegMovie::SeekToPosition(
  475.     REFTIME rt,
  476.     BOOL bFlushData
  477.     )
  478. {
  479.     HRESULT hr=S_OK;
  480.     LONGLONG llTime =
  481.         LONGLONG(m_TimeFormat == TIME_FORMAT_MEDIA_TIME ? rt * double(UNITS) : rt);
  482.  
  483.     if (m_Ms != NULL) {
  484.  
  485.         FILTER_STATE fs;
  486.         m_Mc->GetState(100, (OAFilterState *)&fs);
  487.  
  488.         hr = m_Ms->SetPositions(&llTime, AM_SEEKING_AbsolutePositioning, NULL, 0);
  489.  
  490.         // This gets new data through to the renderers
  491.  
  492.         if (fs == State_Stopped && bFlushData){
  493.             m_Mc->Pause();
  494.             hr = m_Mc->GetState(INFINITE, (OAFilterState *)&fs);
  495.             m_Mc->Stop();
  496.         }
  497.  
  498.         if (SUCCEEDED(hr)) {
  499.             return TRUE;
  500.         }
  501.     }
  502.     return FALSE;
  503. }
  504.  
  505.